using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;

namespace Taxes.EXIF
{
    /// <summary>
    /// Provides methods that encapsulate methods to use on images.
    /// </summary>
    public class ImageUtility
    {
        public ImageUtility(Bitmap bitmap)
        {
            _bitmap = bitmap;
        }

        public ImageUtility(string bitmapFilename)
        {
            _bitmap = new Bitmap(bitmapFilename);
            _bitmapFilename = bitmapFilename;
        }

        ~ImageUtility()
        {
            _bitmap.Dispose();
        }

        public void Dispose()
        {
            _bitmap.Dispose();
        }

        private Bitmap _bitmap;
        public Bitmap Bitmap
        {
            get 
            {
                if (_bitmap == null && _bitmapFilename != null)
                    _bitmap = new Bitmap(_bitmapFilename);
                return _bitmap; 
            }
        }

        private string _bitmapFilename;
        public string BitmapFilename
        {
            get { return _bitmapFilename; }
        }

        private Exif _exif=null;
        public Exif Exif
        {
            get
            {
                if (_exif == null)
                    _exif = new Exif(Bitmap);
                return _exif;
            }
        }

        private System.IO.FileInfo _fileInfo;
        public System.IO.FileInfo FileInfo
        {
            get
            {
                if (_fileInfo == null && !String.IsNullOrEmpty(_bitmapFilename))
                    _fileInfo = new System.IO.FileInfo(_bitmapFilename);

                return _fileInfo;
            }

        }

        /// <summary>
        /// Creates and save a thumbnail of an image.
        /// </summary>
        /// <param name="thumbnailFilePath">The full path to save the thumbnail to.</param>
        /// <param name="width">The maximum width of the thumbnail to create.</param>
        /// <param name="height">The maximum height of the thumbnail to create.</param>
        public void CreateThumbnail(string thumbnailFilePath, int width, int height)
        {
            CreateThumbnail(thumbnailFilePath, width, height, InterpolationMode.Default);
        }

        /// <summary>
        /// Creates and save a thumbnail of an image.
        /// </summary>
        /// <param name="thumbnailFilePath">The full path to save the thumbnail to.</param>
        /// <param name="width">The maximum width of the thumbnail to create.</param>
        /// <param name="height">The maximum height of the thumbnail to create.</param>
        /// <param name="interpolationMode">The Interpolation of the thumbnailing (HighQualityBicubic provides best quality)</param>
        public void CreateThumbnail(string thumbnailFilePath, int width, int height, InterpolationMode interpolationMode)
        {
            if (thumbnailFilePath == null)
                throw new ArgumentNullException("thumbnailFilePath");

            string directory = System.IO.Path.GetDirectoryName(thumbnailFilePath);
            //If we are provided a directory name, check to see if the directory exists
            if (!String.IsNullOrEmpty(directory) && !System.IO.Directory.Exists(directory))
            { 
                System.IO.Directory.CreateDirectory(directory);
            }

            Bitmap bmpTarget = CreateThumbnail(width, height, interpolationMode);

            // Save the new image
            bmpTarget.Save(thumbnailFilePath, ImageFormat.Jpeg);

            bmpTarget.Dispose();
        }

        /// <summary>
        /// Creates a scaled thumbnail.
        /// </summary>
        /// <param name="width">The maximum width of the thumbnail to create.</param>
        /// <param name="height">The maximum height of the thumbnail to create.</param>
        /// <returns>A bitmap thumbnail of the source image.</returns>
        public Bitmap CreateThumbnail(int width, int height)
        {
            return CreateThumbnail(width, height, InterpolationMode.Default);
        }

        /// <summary>
        /// Creates a scaled thumbnail.
        /// </summary>
        /// <param name="width">The maximum width of the thumbnail to create.</param>
        /// <param name="height">The maximum height of the thumbnail to create.</param>
        /// <param name="interpolationMode">The Interpolation of the thumbnailing (HighQualityBicubic provides best quality)</param>
        /// <returns>A bitmap thumbnail of the source image.</returns>
        public Bitmap CreateThumbnail(int width, int height, InterpolationMode interpolationMode)
        {
            //Calculate scales
            float x = ((float)Bitmap.Width / (float)width);
            float y = ((float)Bitmap.Height / (float)height);

            float factor = Math.Max(x, y);
            if (factor < 1)
                factor = 1;

            int thWidth = (int)Math.Round((Bitmap.Width / factor), 0);
            int thHeight = (int)Math.Round((Bitmap.Height / factor), 0);

            // Set the size of the target image
            Bitmap bmpTarget = new Bitmap(thWidth, thHeight);

            Graphics grfxThumb = Graphics.FromImage(bmpTarget);
            grfxThumb.InterpolationMode = interpolationMode;

            // Draw the original image to the target image
            grfxThumb.DrawImage(Bitmap, new Rectangle(0, 0, thWidth, Convert.ToInt32(thWidth * Bitmap.Height / Bitmap.Width)));

            grfxThumb.Dispose();
            return bmpTarget;
        }

        public byte[] ComputeHash()
        {
           System.IO.MemoryStream ms = new System.IO.MemoryStream();
           Bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
           byte[] bytes = ms.ToArray();

           System.Security.Cryptography.SHA1Managed sha = new System.Security.Cryptography.SHA1Managed();
           return sha.ComputeHash(bytes); 
        }

        public string ComputeBase64Hash()
        {
            return System.Convert.ToBase64String(ComputeHash());
        }

        public static bool ThumbnailCallback()
        {
            return false;
        }
    }
}
